import base64
import json
import pickle

from django.http import JsonResponse, HttpResponseBadRequest
from django.shortcuts import render

# Create your views here.
from django.views import View

from django_redis import get_redis_connection

from apps.goods.models import SKU


# http://www.meiduo.site:8800/carts/
class CartsView(View):
    def post(self, request):
        """
        购物车添加
        :param request:
        :return:
        """
        # 1. 获取参数  商品id 和 商品数量
        json_data = json.loads(request.body)
        sku_id = json_data.get('sku_id')
        count = json_data.get('count')
        # 校验参数  是否存在该商品
        try:
            SKU.objects.get(id=sku_id)
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '商品不存在'})
        # 数量是否是数字
        try:
            count = int(count)
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})
        # 判断用户是否登录
        user = request.user
        # 如果登录存入redis
        if user.is_authenticated:
            # 连接redis
            redis_conn = get_redis_connection('carts')
            # 存入hash 字典    cart_userId   {sku_id:count}
            redis_conn.hset('cart_%s' % user.id, sku_id, count)
            # 存入set集合  是否选中  selected_userId  [sku_id1,sku_id2,sku_id3]
            redis_conn.sadd("selected_%s" % user.id, sku_id)
            return JsonResponse({'code': 0, 'errmsg': 'ok'})
        # 没有登录购物车数据存入cookie
        else:
            import base64
            import pickle
            # 先获取cookie
            cart_cookie = request.COOKIES.get('cart')
            # 如果有cookie就解码  base64解码  pickle二进制数据转换
            if cart_cookie:
                carts = pickle.loads(base64.b64decode(cart_cookie))
            # 没有就创建新字典
            else:
                carts = {}

            # 如果商品已经存在购物车  就把数量+1
            if sku_id in carts:
                count_ori = carts[sku_id]['count']
                count += count_ori

            # 组织数据存入cookie
            carts[sku_id] = {
                'count': count,
                'selected': True
            }
            # 稍微加密一下
            carts_bytes = pickle.dumps(carts)
            b64carts = base64.b64encode(carts_bytes)
            # 存入cookie
            response = JsonResponse({'code': 0, 'errmsg': 'ok'})
            response.set_cookie('cart', b64carts.decode(), max_age=3600 * 24 * 10)
            return response

    def get(self, request):
        # 判断用户是否登录
        user = request.user

        if user.is_authenticated:

            # 如果登录连接redis
            redis_conn = get_redis_connection('carts')
            # 取出redis内的所有购物车数据
            sku_id_count = redis_conn.hgetall('cart_%s' % user.id)
            # 取出所有选中的列表
            selected_sku_ids = redis_conn.smembers('selected_%s' % user.id)
            # 组织数据
            carts = {}
            # redis取出是二进制数据  要强转一下
            for sku_id, count in sku_id_count.items():
                carts[int(sku_id)] = {
                    'count': int(count),
                    'selected': sku_id in selected_sku_ids
                }
        else:
            # 没有登录取出cookie
            cart_cookie = request.COOKIES.get('cart')
            # 有cookie 就解码  没有cookie就创建一个空字典
            if cart_cookie:
                carts = pickle.loads(base64.b64decode(cart_cookie))
            else:
                carts = {}

        # 取出数据中所有的key  为sku_id
        sku_ids = carts.keys()

        # 查询所有商品  返回出id在购物车列表内的
        skus = SKU.objects.filter(id__in=sku_ids)

        # 组织数据  id  name  price 图片  数量  是否被选中
        sku_list = []
        for sku in skus:
            sku_list.append({
                'id': sku.id,
                'name': sku.name,
                'price': sku.price,
                'default_image_url': sku.default_image.url if sku.default_image else "",
                'count': carts[sku.id]['count'],
                'selected': carts[sku.id]['selected'],
            })

        # 返回数据
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_skus': sku_list})

    def put(self, request):
        # 获取参数  数量  是否选中 和 商品id
        json_data = json.loads(request.body)

        count = json_data.get('count')
        selected = json_data.get('selected')
        sku_id = json_data.get('sku_id')
        # 校验参数  商品是否真实存在  数量是否是数字 selected是否是布尔值
        try:
            SKU.objects.get(id=sku_id)
        except Exception as e:
            print(e)
            return HttpResponseBadRequest('商品不存在')
        try:
            count = int(count)
        except Exception as e:
            print(e)
            return HttpResponseBadRequest('参数错误')

        if not isinstance(selected, bool):
            return HttpResponseBadRequest('商品不存在')

        # 判断用户是否登录
        user = request.user

        if user.is_authenticated:
            # 登录连接redis
            redis_conn = get_redis_connection('carts')
            # 修改数据
            redis_conn.hset('cart_%s' % user.id, sku_id, count)
            # 修改是否被选中
            if selected:
                redis_conn.sadd('selected_%s' % user.id, sku_id)

            else:
                redis_conn.srem('selected_%s' % user.id, sku_id)

            # 组织返回前端的数据
            cart_sku = {
                'count': count,
                'selected': selected,
                'sku_id': sku_id,
            }

            return JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_sku': cart_sku})
        else:
            # 没有登录  取出cookie
            cart_cookie = request.COOKIES.get('cart')
            # 解码
            carts = pickle.loads(base64.b64decode(cart_cookie))

            # 修改数据
            carts[sku_id]['count'] = count
            carts[sku_id]['selected'] = selected

            # 稍微加密
            carts_bytes = pickle.dumps(carts)
            b64carts = base64.b64encode(carts_bytes)

            # 组织返回前端的数据
            cart_sku = {
                'count': count,
                'selected': selected,
                'sku_id': sku_id,
            }

            # 添加到cookie
            response = JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_sku': cart_sku})
            response.set_cookie('cart', b64carts.decode(), max_age=3600 * 24 * 10)
            return response

    def delete(self, request):
        # 获取参数  要删除购物车内哪一个商品
        json_data = json.loads(request.body)
        sku_id = json_data.get('sku_id')
        #  校验参数
        try:
            SKU.objects.get(id=sku_id)
        except Exception as e:
            print(e)
            return HttpResponseBadRequest('商品不存在')

        # 判断用户是否登录
        user = request.user
        if user.is_authenticated:
            # 如果登录 连接redis
            redis_conn = get_redis_connection('carts')
            # 删除数据
            redis_conn.hdel('cart_%s' % user.id, sku_id)
            redis_conn.srem('selected_%s' % user.id, sku_id)
            # 返回响应
            return JsonResponse({'code': 0, 'errmsg': 'ok'})
        else:
            # 没有登录 获取cookie
            cart_cookie = request.COOKIES.get('cart')
            # 解码
            carts = pickle.loads(base64.b64decode(cart_cookie))
            # 删除cookie内的该商品
            del carts[sku_id]
            # 加密
            carts_bytes = pickle.dumps(carts)
            base64_carts = base64.b64encode(carts_bytes)
            # 设置cookie  返回响应
            response = JsonResponse({'code': 0, 'errmsg': 'ok'})
            response.set_cookie('cart', base64_carts.decode(), max_age=3600 * 24 * 10)
            return response


# http://www.meiduo.site:8800/carts/selection/
class CartsSelect(View):
    def put(self, request):
        # 获取参数  selected全选按钮是否勾选  布尔值
        json_data = json.loads(request.body)
        selected = json_data.get('selected')
        # 校验参数
        if not isinstance(selected, bool):
            return HttpResponseBadRequest('商品不存在')
        # 判断用户是否登录
        user = request.user

        if user.is_authenticated:
            # 如果登录  连接redis
            redis_conn = get_redis_connection('carts')
            # 获取到所有购物车数据
            cart_list = redis_conn.hgetall('cart_%s' % user.id)
            # 取出key  key为商品id
            cart_key_list = cart_list.keys()
            # 遍历商品id
            for key in cart_key_list:
                # 如果全选选中  就把所有商品id添加到set集合  不用去重 因为set集合自动去重
                if selected:
                    redis_conn.sadd('selected_%s' % user.id, key)
                # 如果没有勾选  就把set集合内所有商品id删除
                else:
                    redis_conn.srem('selected_%s' % user.id, key)

            return JsonResponse({'code': 0, 'errmsg': 'ok'})
        else:
            # 没有登录就获取cookie
            cart_cookie = request.COOKIES.get('cart')
            # 解码
            carts = pickle.loads(base64.b64decode(cart_cookie))
            # 遍历字典  拆包  k为sku_id  v 为 {count:xxx,selected:bool}
            for k, v in carts.items():
                # 如果选中  就把所有的sku_id的selected设置为True
                if selected:
                    v['selected'] = True
                # 没有选中则设置为False
                else:
                    v['selected'] = False
            # 加密
            b64carts = base64.b64encode(pickle.dumps(carts))
            # 设置cookie  返回响应
            response = JsonResponse({'code': 0, 'errmsg': 'ok'})
            response.set_cookie('cart', b64carts.decode(), max_age=3600 * 24 * 10)
            return response


# http://www.meiduo.site:8800/carts/simple/
class CartsSimpleView(View):
    def get(self, request):
        # 获取用户对象
        user = request.user
        # 组织数据的列表
        cart_skus = []
        # 如果用户存在就去连接redis取出购物车数据
        if user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            cart_data = redis_conn.hgetall('cart_%s' % user.id)
            sku_id_list = cart_data.keys()

            for sku_id in sku_id_list:
                count = int(cart_data.get(sku_id))

                sku = SKU.objects.get(id=int(sku_id))
                # 组织数据添加到列表
                cart_skus.append({
                    'id': sku.id,
                    'name': sku.name,
                    'count': count,
                    'default_image_url': sku.default_image.url if sku.default_image else "",
                })
            return JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_skus': cart_skus})
        else:
            # 如果用户不存在就去cookie中取出购物车数据
            cart_cookie = request.COOKIES.get('cart')
            if cart_cookie:
                # 解码
                cart_cookie_data = pickle.loads(base64.b64decode(cart_cookie))
                # 遍历商品id
                sku_id_list = cart_cookie_data.keys()

                for sku_id in sku_id_list:
                    count = cart_cookie_data[sku_id]['count']

                    sku = SKU.objects.get(id=int(sku_id))
                    # 组织数据添加到列表
                    cart_skus.append({
                        'id': sku.id,
                        'name': sku.name,
                        'count': count,
                        'default_image_url': sku.default_image.url if sku.default_image else "",
                    })
            else:
                cart_skus = []
            return JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_skus': cart_skus})
